﻿#if !NET40 &&  !NET45
using Newtonsoft.Json;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;


namespace Anno
{
    /// <summary>
    /// 请求帮助类
    /// </summary>
    public class HttpHelper
    {
        public static readonly HttpHelper Instance;
        static HttpHelper()
        {
            Instance = new HttpHelper();
        }
        /// <summary>
        /// 不同url分配不同HttpClient
        /// </summary>
        public static ConcurrentDictionary<string, HttpClient> dictionary = new ConcurrentDictionary<string, HttpClient>();

        private HttpClient GetHttpClient(string url)
        {
            var uri = new Uri(url);
            var key = uri.Scheme + uri.Host;
            if (!dictionary.TryGetValue(key, out var httpClient))
            {
                httpClient = new HttpClient();
                dictionary.TryAdd(key, httpClient);
            }
            return httpClient;
        }
        /// <summary>
        /// 异步(GET/POST/PUT/DELETE)请求
        /// </summary>
        /// <param name="httpMethod">GET/POST/PUT/DELETE</param>
        /// <param name="url">url地址</param>
        /// <param name="jsonString">请求参数（Json字符串）</param>
        /// <param name="headers">webapi做用户认证</param>
        /// <param name="parameters">GET请求参数</param>
        /// <returns></returns>
        public async Task<HttpResponseMessage> RequestAsync(string httpMethod, string url, string jsonString = ""
            , IDictionary<string, string> headers = null, IDictionary<string, string> parameters = null)
        {
            if (httpMethod.Equals("POST", StringComparison.OrdinalIgnoreCase))
            {
                return await PostAsync(url, jsonString, headers);
            }
            else if (httpMethod.Equals("GET", StringComparison.OrdinalIgnoreCase))
            {
                return await GetAsync(url, headers);
            }
            else if (httpMethod.Equals("PUT", StringComparison.OrdinalIgnoreCase))
            {
                return await PutAsync(url, jsonString, headers);
            }
            else if (httpMethod.Equals("DELETE", StringComparison.OrdinalIgnoreCase))
            {
                return await DeleteAsync(url, headers);
            }
            else
            {
                return await PostAsync(url, jsonString, headers);
            }
        }
        /// <summary>
        /// 异步(GET/POST/PUT/DELETE)请求
        /// </summary>
        /// <param name="httpMethod">GET/POST/PUT/DELETE</param>
        /// <param name="url">url地址</param>
        /// <param name="jsonString">请求参数（Json字符串）</param>
        /// <param name="headers">webapi做用户认证</param>
        /// <param name="parameters">GET请求参数</param>
        /// <returns></returns>
        public async Task<HttpResponseMessage> RequestAsync<T>(string httpMethod, string url, T content
            , IDictionary<string, string> headers = null, IDictionary<string, string> parameters = null) where T : class
        {
            var jsonString = "";
            if (content != null)
            {
                jsonString = content is string ? content.ToString() : JsonConvert.SerializeObject(content);
            }
            return await RequestAsync(httpMethod, url, jsonString, headers, parameters);
        }
        /// <summary>
        /// Post请求
        /// </summary>
        /// <param name="url">url地址</param>
        /// <param name="jsonString">请求参数（Json字符串）</param>
        /// <param name="headers">webapi做用户认证</param>
        /// <returns></returns>
        public async Task<HttpResponseMessage> PostAsync(string url, string jsonString, IDictionary<string, string> headers = null)
        {
            if (string.IsNullOrWhiteSpace(jsonString))
                jsonString = "{}";
            var content = new StringContent(jsonString);
            content.Headers.ContentType = new MediaTypeHeaderValue("application/json");

            if (headers != null && headers.Any())
            {
                //如果有headers认证等信息，则每个请求实例一个HttpClient
                using (HttpClient http = new HttpClient())
                {
                    BuildHeader(http, headers);
                    return await http.PostAsync(new Uri(url), content);
                }
            }
            else
            {
                return await GetHttpClient(url).PostAsync(new Uri(url), content);
            }
        }

        /// <summary>
        /// Post请求
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="url">url地址</param>
        /// <param name="content">请求参数</param>
        /// <param name="headers">webapi做用户认证</param>
        /// <returns></returns>
        public async Task<HttpResponseMessage> PostAsync<T>(string url, T content, IDictionary<string, string> headers = null) where T : class
        {
            return await PostAsync(url, JsonConvert.SerializeObject(content), headers);
        }

        /// <summary>
        /// Get请求
        /// </summary>
        /// <param name="url">url地址</param>
        /// <param name="headers">webapi做用户认证</param>
        /// <param name="parameters">GET请求参数</param>
        /// <returns></returns>
        public async Task<HttpResponseMessage> GetAsync(string url, IDictionary<string, string> parameters = null, IDictionary<string, string> headers = null)
        {
            //设置请求参数
            if (parameters != null && parameters.Any())
            {
                url += (url.Contains("?") ? "&" : "?") + BuildQuery(parameters, Encoding.UTF8);
            }
            if (headers != null && headers.Any())
            {
                //如果有headers认证等信息，则每个请求实例一个HttpClient
                using (HttpClient http = new HttpClient())
                {
                    BuildHeader(http, headers);
                    return await http.GetAsync(url);
                }
            }
            else
            {
                return await GetHttpClient(url).GetAsync(url);
            }
        }

        /// <summary>
        /// Put请求
        /// </summary>
        /// <param name="url">url地址</param>
        /// <param name="jsonString">请求参数（Json字符串）</param>
        /// <param name="headers">webapi做用户认证</param>
        /// <returns></returns>
        public async Task<HttpResponseMessage> PutAsync(string url, string jsonString, IDictionary<string, string> headers = null)
        {
            if (string.IsNullOrWhiteSpace(jsonString))
                jsonString = "{}";
            var content = new StringContent(jsonString);
            content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
            if (headers != null && headers.Any())
            {
                //如果有headers认证等信息，则每个请求实例一个HttpClient
                using (HttpClient http = new HttpClient())
                {
                    BuildHeader(http, headers);
                    return await http.PutAsync(url, content);
                }
            }
            else
            {
                return await GetHttpClient(url).PutAsync(url, content);
            }
        }

        /// <summary>
        /// Put请求
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="url">url地址</param>
        /// <param name="content">请求参数</param>
        /// <param name="headers">webapi做用户认证</param>
        /// <returns></returns>
        public async Task<HttpResponseMessage> PutAsync<T>(string url, T content, IDictionary<string, string> headers = null)
        {
            return await PutAsync(url, JsonConvert.SerializeObject(content), headers);
        }

        /// <summary>
        /// Delete请求
        /// </summary>
        /// <param name="url"></param>
        /// <param name="headers">webapi做用户认证</param>
        /// <returns></returns>
        public async Task<HttpResponseMessage> DeleteAsync(string url, IDictionary<string, string> headers = null)
        {
            if (headers != null && headers.Any())
            {
                //如果有headers认证等信息，则每个请求实例一个HttpClient
                using (HttpClient http = new HttpClient())
                {
                    BuildHeader(http, headers);
                    return await http.DeleteAsync(url);
                }
            }
            else
            {
                return await GetHttpClient(url).DeleteAsync(url);
            }

            //SocketsHttpHandler socketsHandler = new SocketsHttpHandler()
            //{
            //    SslOptions = new System.Net.Security.SslClientAuthenticationOptions()
            //    {
            //        RemoteCertificateValidationCallback = (sender, cer, chain, err) => true
            //    }
            //};
            //var httpClient = new HttpClient(socketsHandler);
        }
       
        //-----------------------------------------------------------------------------------------------------
        /// <summary>
        /// 设置HTTP 标头的名称/值对的集合
        /// </summary>
        /// <param name="http"></param>
        /// <param name="headers"></param>
        void BuildHeader(HttpClient http, IDictionary<string, string> headers)
        {
            if (http == null || headers.IsNullOrEmpty_()) return;
            if (headers.ContainsKey("Accept"))
                headers.Remove("Accept");
            if (headers.ContainsKey("Accept-Encoding"))
                headers.Remove("Accept-Encoding");
            if (headers.ContainsKey("Connection"))
                headers.Remove("Connection");
            if (headers.ContainsKey("Content-Type"))
                headers.Remove("Content-Type");
            if (headers.ContainsKey("Expect"))
                headers.Remove("Expect");
            foreach (var item in headers)
            {
                if (!string.IsNullOrWhiteSpace(item.Key) && !string.IsNullOrWhiteSpace(item.Value))
                {
                    http.DefaultRequestHeaders.Remove(item.Key);
                    http.DefaultRequestHeaders.TryAddWithoutValidation(item.Key, item.Value);
                }
            }
        }
        /// <summary>
        /// 组装普通文本请求参数。
        /// </summary>
        /// <param name="parameters">Key-Value形式请求参数字典</param>
        /// <returns>URL编码后的请求数据</returns>
        string BuildQuery(IDictionary<string, string> parameters, Encoding encode = null)
        {
            StringBuilder postData = new StringBuilder();
            bool hasParam = false;
            IEnumerator<KeyValuePair<string, string>> dem = parameters.GetEnumerator();
            while (dem.MoveNext())
            {
                string name = dem.Current.Key;
                string value = dem.Current.Value;
                // 忽略参数名或参数值为空的参数
                if (!string.IsNullOrEmpty(name))//&& !string.IsNullOrEmpty(value)
                {
                    if (hasParam)
                    {
                        postData.Append("&");
                    }
                    postData.Append(name);
                    postData.Append("=");
                    if (encode == null)
                    {
                        postData.Append(System.Web.HttpUtility.UrlEncode(value, encode));
                    }
                    else
                    {
                        postData.Append(value);
                    }
                    hasParam = true;
                }
            }
            return postData.ToString();
        }
    }
}
#endif
